package com.gjy.spring.boot3;

import com.gjy.spring.boot.HelloBeanA;
import com.google.common.collect.Sets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.*;
import org.springframework.context.support.GenericApplicationContext;

import java.lang.reflect.Method;

/**
 * @author 宫静雨
 * @version 1.0
 * @since 2023-12-18 09:18:58
 */
@SpringBootApplication
public class Boot1App {

    private static final Logger log = LoggerFactory.getLogger(Boot1App.class);

    public static void main(String[] args) throws Exception {
        //SpringApplication.run(SpringRunApp.class, args);
        //1. 获取BeanDefinition 源
        SpringApplication application = new SpringApplication(Boot1App.class);
        // 设置多个源
        application.setSources(Sets.newHashSet("classpath:b01.xml"));
        //2. 推断应用类型
        // this.webApplicationType = WebApplicationType.deduceFromClasspath();
        Method method = WebApplicationType.class.getDeclaredMethod("deduceFromClasspath");
        method.setAccessible(true);
        // 静态方法，执行无需对象
        Object o = method.invoke(null);
        log.info("应用类型为: {}", o);
        //3. ApplicationContext 初始化器
        application.addInitializers(new ApplicationContextInitializer<ConfigurableApplicationContext>() {
            @Override
            public void initialize(ConfigurableApplicationContext applicationContext) {
                if (applicationContext instanceof GenericApplicationContext) {
                    GenericApplicationContext context = (GenericApplicationContext) applicationContext;
                    context.registerBean("helloBeanA", HelloBeanA.class);
                }
            }
        });
        //4. 监听器与事件
        application.addListeners(new ApplicationListener<ApplicationEvent>() {
            @Override
            public void onApplicationEvent(ApplicationEvent event) {
                log.info("事件类型为: {}", event.getClass());
            }
        });
        //5. 主类推断
        Method m2 = application.getClass().getDeclaredMethod("deduceMainApplicationClass");
        m2.setAccessible(true);
        Object o2 = m2.invoke(application);
        log.info("主类推断: {}", o2);

        ConfigurableApplicationContext context = application.run(args);
        for (String definitionName : context.getBeanDefinitionNames()) {
            BeanDefinition definition = context.getBeanFactory().getBeanDefinition(definitionName);
            String description = definition.getResourceDescription();
            log.info("{} -- {}", definitionName, description);
        }

        context.close();
    }
}
